
from flask import request
from utils.randomUtils import generate_random_token, generate_random_by_time
import threading
from .baseGraphNode import *
from .httpGraphNode import HttpGraphNode
from ..execute.baseExeHis import BaseExeHis
from .sessionInfo import SessionInfo
from collections import defaultdict
from eventlet.semaphore import Semaphore
import uuid

class HttpInGraphNode(BaseGraphNode):
    def __init__(self, id:str, data:dict, graphNodeManager, random_key:str):
        super().__init__(id, data, graphNodeManager, random_key)
        self.route = data['data']['route']
        self.enWS = data['data'].get('enWS', True)
        self.enInterrupt = True#data['data'].get('enInterrupt', True)
        if self.graphNodeManager.http_node is not None:
            self.full_url = self.graphNodeManager.http_node.full_url
        else:
            self.graphNodeManager.http_node = HttpGraphNode(generate_random_by_time(), self.data, self.graphNodeManager, self.random_key)
            self.full_url = self.graphNodeManager.http_node.full_url
        self._ws_token = self.full_url
        self.running = False
        self.session_locks = defaultdict(Semaphore)  # 每个session_id独立锁
        self.session_id_2_running_id = {}

    def execute(self, session_info: SessionInfo=None, exe_his: BaseExeHis=None, **kwargs):
        if (not self.running):
            if self.route in self.graphNodeManager.project.onlineRoutes:
                self.graphNodeManager.project.onlineRoutes.pop(self.route)
            self.running = True
            
            socketio_instance = self.graphNodeManager.http_node.get_socketio_instance()
            route = self.route
            full_url = self.full_url

            @socketio_instance.on(route, namespace=full_url)
            def handle_message(msg):
                if 'data' not in msg:
                    return
                msgdata = msg['data']
                id = msg.get('id', None)
                if id is None:
                    print(f'{self.name} handle_message id is None')
                    return
                
                session_info = self.graphNodeManager.get_session_info(id, socketio_instance, request.sid, self.full_url) 
                with session_info.out_write_lock:
                    self.session_id_2_running_id[session_info.id]=str(uuid.uuid4()).replace('-', '')[:16]
                    if session_info.out.get(self.id,None) is None: session_info.out[self.id] = {}
                    if 'query-msg' not in session_info.out[self.id] : session_info.out[self.id]['query-msg'] = []
                    session_info.out[self.id]['query-msg'].append(Msg(content=msgdata, role='user', msg_type='text'))
                self.executed_num += 1
                self.flow_next(session_info, trigger=self, running_id=self.session_id_2_running_id[session_info.id],type='text', role='user') # ExecutionTask

            
            self.graphNodeManager.project.addOnlineRoute(self.route, 'message', self.name)
            print(f'WebSocket app created and listening, namespace: {self.full_url}')

    
